#include <iostream>
#include <string>
#include <bitset>
#include <fstream>
#include <vector>

#include "HexJudgerConsole.h"
#include "DummyVCSolver.h"

HexJudgerConsole::HexJudgerConsole(int argc, char ** argv): QObject()
{
	//printf("aaa");
}

HexJudgerConsole::~HexJudgerConsole()
{
	if (engine1)
	{
		delete engine1;
	}

	if (engine2)
	{
		delete engine2;
	}
}

void HexJudgerConsole::readPath()
{
	gets_s(path1);
	gets_s(path2);
}

void HexJudgerConsole::createEngine()
{
	engine1 = new QProcess();
	engine2 = new QProcess();
}

void HexJudgerConsole::startEngine()
{
	engine1->start(path1);
	engine1->waitForStarted(-1);
	engine2->start(path2);
	engine2->waitForStarted(-1);
}

void HexJudgerConsole::connectEngineToSlots()
{
	connect(engine1, &QProcess::readyReadStandardOutput, this, &HexJudgerConsole::onEngine1ReadyRead);
	connect(engine2, &QProcess::readyReadStandardOutput, this, &HexJudgerConsole::onEngine2ReadyRead);
}

void HexJudgerConsole::writeAndWait(QProcess * process, const char * str)
{
	process->write(str);
	process->waitForBytesWritten(-1);
}

void HexJudgerConsole::killProcess()
{
	engine1->kill();
	engine1->waitForFinished(-1);
	engine2->kill();
	//engine2->terminate();
	engine2->waitForFinished(-1);
}

int HexJudgerConsole::startSimulation()
{
	writeAndWait(engine1, "11\r\n");
	engine1->waitForReadyRead();
	writeAndWait(engine2, "11\r\n");
	engine2->waitForReadyRead();

	writeAndWait(engine1, "1\r\n");
	engine1->waitForReadyRead();
	writeAndWait(engine2, "2\r\n");
	engine2->waitForReadyRead();

	writeAndWait(engine1, "500\r\n");
	//engine1->waitForReadyRead();
	while (!switchFlag)
	{
		engine1->waitForReadyRead(-1);
	}
	switchFlag = false;
	//lastMove = flip(lastMove);
	if (board.get(lastMove) != 0) {
		printf("error\n");
	}
	board.set(lastMove, 1);
	printBoard(board);
	//printf("%d\n", board.gameover());

	while (1)
	{
		char temp[50];
		int win;
		sprintf(temp, "%d\r\n", lastMove);

		writeAndWait(engine2, temp);
		engine2->waitForReadyRead(-1);

		writeAndWait(engine2, "500\r\n");
		while (!switchFlag)
		{
			engine2->waitForReadyRead(-1);
		}
		switchFlag = false;
		//lastMove = flip(lastMove);
		if (board.get(lastMove) != 0) {
			printf("error\n");
		}
		board.set(lastMove, 2);
		printBoard(board);
		//win = board.gameover();
		win = DummyVCSolver::solve(board);
		if (win != 0)
		{
			killProcess();
			return win;
		}

		sprintf(temp, "%d\r\n", lastMove);

		writeAndWait(engine1, temp);
		engine1->waitForReadyRead();

		writeAndWait(engine1, "500\r\n");
		//engine1->waitForReadyRead();
		while (!switchFlag)
		{
			engine1->waitForReadyRead(-1);
		}
		switchFlag = false;
		//lastMove = flip(lastMove);
		if (board.get(lastMove) != 0) {
			printf("error\n");
		}
		board.set(lastMove, 1);
		printBoard(board);
		//win = board.gameover();
		win = DummyVCSolver::solve(board);
		if (win != 0)
		{
			killProcess();
			return win;
		}
	}
}

void HexJudgerConsole::onEngine1ReadyRead()
{
	//static int cmd = 0;

	//printf("cmd = %d\n", cmd);

	while (engine1->canReadLine())
	{
		std::string str = engine1->readLine().toStdString();
		//printf("%d: from engine1: %s", cmd1, str.c_str());

		if (str == "MOVE\r\n" && cmd1 == 2)
		//if (str == "MOVE\r\n")
		{
			std::string temp = engine1->readLine().toStdString();
			sscanf(temp.c_str(), "%d", &lastMove);
			printf("lastMove1: %d\n", lastMove);
			switchFlag = true;
		}
	}

	if (cmd1 != 2)
	{
		cmd1++;
	}
}

void HexJudgerConsole::onEngine2ReadyRead()
{
	//static int cmd = 0;

	//printf("cmd = %d\n", cmd);

	while (engine2->canReadLine())
	{
		std::string str = engine2->readLine().toStdString().c_str();
		//printf("%d: from engine2: %s", cmd2, str.c_str());

		if (str == "MOVE\r\n" && cmd2 == 2)
		//if (str == "MOVE\r\n")
		{
			std::string temp = engine2->readLine().toStdString();
			sscanf(temp.c_str(), "%d", &lastMove);
			printf("lastMove2: %d\n", lastMove);
			switchFlag = true;
		}
	}

	if (cmd2 != 2)
		cmd2++;
}

void HexJudgerConsole::setPath(const char * str1, const char * str2)
{
	strcpy(path1, str1);
	strcpy(path2, str2);
}

void HexJudgerConsole::printBoard(const Board & board) {
	for (int i = 0; i < 11; i++) {
		for (int j = 0; j < i; j++) {
			printf(" ");
		}

		for (int j = 0; j < 11; j++) {
			switch (board.get(i, j)) {
			case 0:
				printf(". ");
				break;
			case 1:
				printf("x ");
				break;
			case 2:
				printf("o ");
				break;
			}
		}
		printf("\n");
	}
}